package com.suray.wcs.service.pojo.rgv.rgv.protocol.message;

import com.suray.basic.wcs.utils.LoggerUtil;
import com.suray.basic.wcs.utils.WcsFuncUtil;
import com.suray.basic.wcs.utils.typedef.Byte;
import com.suray.basic.wcs.utils.typedef.DWord;
import com.suray.basic.wcs.utils.typedef.Word;
import com.suray.commin.core.utils.SpringContextHolder;
import com.suray.commin.exception.OrderExecuteException;
import com.suray.wcs.service.enums.CodeType;
import com.suray.wcs.service.pojo.DrivingParam;
import com.suray.wcs.service.pojo.LiftParam;
import com.suray.wcs.service.pojo.ResParam;
import com.suray.wcs.service.pojo.Rgv;
import com.suray.wcs.service.pojo.rgv.rgv.protocol.base.RgvRecMessage;
import com.suray.wcs.service.pojo.rgv.rgv.protocol.exception.FrameLocationException;
import com.suray.wcs.service.pojo.rgv.rgv.protocol.exception.MessageCompleteException;
import com.suray.wcs.service.pojo.rgv.rgv.protocol.exception.MessageErrorException;
import com.suray.wcs.service.pojo.rgv.rgv.protocol.util.DebugCommType;
import com.suray.wcs.service.pojo.rgv.rgv.protocol.util.RgvDebugMessageType;
import com.suray.wcs.service.pojo.rgv.rgv.protocol.util.RgvMessageType;
import com.suray.wcs.service.system.service.impl.CodeDBServiceImpl;
import com.suray.wcs.service.util.WcsUtil;

import java.io.IOException;
import java.util.Arrays;

public class RgvDebugCmdRecMessage extends RgvRecMessage {

    private final static CodeDBServiceImpl codedbService = SpringContextHolder.getBean(CodeDBServiceImpl.class);

    private final static int END_FRAME_LENGTH = 3;

    private RgvDebugMessageType messageType;

    public RgvDebugCmdRecMessage(Rgv rgv, DebugCommType type) {
        super(rgv, "调试指令接收");

        baseDatas.add(new Word("头帧", "取值0x02FD"));
        baseDatas.add(new Byte("设备ID", "取值范围：0-255， 小车对应设备号"));
        baseDatas.add(new Byte("生命", "0-255"));
        baseDatas.add(new Byte("报文类型", "0:心跳，1：整体任务，2：指令，3：调试指令"));
        baseDatas.add(new Byte("指令序号", "1-255， 唯一标识操作指令，循环自增，溢出变1，；0-代表无指令；与任务序号不可同时存在"));
        baseDatas.add(new Byte("指令ID", "1-255， WCS下发的指令Id"));
        baseDatas.add(new Byte("次指令ID", "1-255， 详细的获取哪个参数或者设置哪个参数"));
        baseDatas.add(new Word("执行结果", "1：进行中，2.执行完成，其他-错误编码"));
        baseDatas.add(new Byte("参数个数", "1-255，参数个数=0时，结果参数占4个字节也填0，个数不为0，一个参数占4字节"));
        addDebugRecParam(type, RgvDebugMessageType.READ_ALL);
    }

    public RgvDebugCmdRecMessage(Rgv rgv, DebugCommType type, RgvDebugMessageType messageType) {
        super(rgv, "调试指令接收");

        baseDatas.add(new Word("头帧", "取值0x02FD"));
        baseDatas.add(new Byte("设备ID", "取值范围：0-255， 小车对应设备号"));
        baseDatas.add(new Byte("生命", "0-255"));
        baseDatas.add(new Byte("报文类型", "0:心跳，1：整体任务，2：指令，3：调试指令"));
        baseDatas.add(new Byte("指令序号", "1-255， 唯一标识操作指令，循环自增，溢出变1，；0-代表无指令；与任务序号不可同时存在"));
        baseDatas.add(new Byte("指令ID", "1-255， WCS下发的指令Id"));
        baseDatas.add(new Byte("次指令ID", "1-255， 详细的获取哪个参数或者设置哪个参数"));
        baseDatas.add(new Word("执行结果", "1：进行中，2.执行完成，其他-错误编码"));
        baseDatas.add(new Byte("参数个数", "1-255，参数个数=0时，结果参数占4个字节也填0，个数不为0，一个参数占4字节"));
        addDebugRecParam(type, messageType);
    }

    private void addEndData() {
        baseDatas.add(new Word("报文长度", "整条报文的长度"));
        baseDatas.add(new Word("校验位", "CRC（循环冗余校验；低位在前，高位在后），采用crc16_modbus"));
        baseDatas.add(new Word("尾帧", "0x3FC"));
    }

    private void addDebugRecParam(DebugCommType type, RgvDebugMessageType messageType) {
        this.messageType = messageType;
        switch (type) {
            case DRIVING_PARAM:
                if (messageType == RgvDebugMessageType.SIMPLE_READ) {
                    simpleRead();
                } else if (messageType == RgvDebugMessageType.READ_DRIVER_VERSION) {
                    return;
                } else if (messageType == RgvDebugMessageType.READ_ALL) {
                    recMoveParam();
                } else {
                    throw new RuntimeException("不支持的调试指令:" + type + messageType);
                }
                break;
            case RES_PARAM:
                if (messageType == RgvDebugMessageType.READ_RES_VERSION) {
                    return;
                } else if (messageType == RgvDebugMessageType.READ_ALL) {
                    res();
                } else {
                    throw new RuntimeException("不支持的调试指令:" + type + messageType);
                }
                break;
            case LIFT_PARAM:
                if (messageType == RgvDebugMessageType.READ_LIFT_VERSION) {
                    return;
                } else if (messageType == RgvDebugMessageType.READ_ALL) {
                    liftParam();
                } else {
                    throw new RuntimeException("不支持的调试指令:" + type + messageType);
                }
                break;
            case SET_ONE_PARAM:
                setOneParam();
                break;
            default:
                throw new RuntimeException("错误的指令，无法识别:" + type);
        }
        addEndData();
    }

    /**
     * 读取版本号
     */
    private void readVersion(int paramNum) {
        addParamByLength(paramNum * 4);
        addEndData();
    }

    private void addParamByLength(int size) {
        for (int i = 0; i < size; i++) {
            baseDatas.add(new Byte("v" + i, ""));
        }
    }

    private void simpleRead() {
        baseDatas.add(new DWord("resultParam", "执行结果参数"));
    }

    public Integer getResultParam() {
        return getValue("resultParam");
    }

    /**
     * 升降参数获取
     */
    private void liftParam() {
        baseDatas.add(new DWord("固件版本", "固件版本"));
        baseDatas.add(new DWord("巷道传感器1数据", "换向巷道状态时，换向激光传感器1的默认数据"));
        baseDatas.add(new DWord("巷道传感器2数据", "换向巷道状态时，换向激光传感器2的默认数据"));
        baseDatas.add(new DWord("坡道传感器1数据", "换向坡道状态时换向激光传感器1的默认数据，一般情况下巷道数值比坡道数值大40"));
        baseDatas.add(new DWord("坡道传感器2数据", "换向坡道状态时换向激光传感器2的默认数据，一般情况下巷道数值比坡道数值大40"));
        baseDatas.add(new DWord("托盘降传感器1数据", "托盘降状态时，托盘激光传感器1的默认数据"));
        baseDatas.add(new DWord("托盘降传感器2数据", "托盘降状态时，托盘激光传感器2的默认数据"));
        baseDatas.add(new DWord("托盘升传感器1数据", "托盘升状态时，托盘激光传感器1的默认数据"));
        baseDatas.add(new DWord("托盘升传感器2数据", "托盘升状态时，托盘激光传感器2的默认数据"));
        baseDatas.add(new DWord("传感器误差值", "传感器误差值"));
        baseDatas.add(new DWord("液压动作高度差", "修改坡道巷道以及托盘升降的高度差"));
        baseDatas.add(new DWord("液压到位后延迟时间", "换向托盘到位后的延迟时间（ms）"));
        baseDatas.add(new DWord("驱动默认最大速度", "驱动器默认的最大速度"));
        baseDatas.add(new DWord("驱动默认加速度", "驱动默认加速度"));
        baseDatas.add(new DWord("驱动默认减速度", "驱动默认减速度"));
        baseDatas.add(new DWord("溢流调平延迟时间", "溢流调平延迟时间"));
        baseDatas.add(new DWord("串联打开时间", "串联打开时间"));
        baseDatas.add(new DWord("并联打开时间", "并联打开时间"));
        baseDatas.add(new DWord("电机转动方向", "电机转动方向"));
        baseDatas.add(new DWord("预留，兼容新宜昌参数", "预留，兼容新宜昌参数"));
        baseDatas.add(new DWord("托盘升绝对编码器数据", "托盘升绝对编码器数据"));
        baseDatas.add(new DWord("托盘降绝对编码器数据", "托盘降绝对编码器数据"));
        baseDatas.add(new DWord("巷道绝对编码器数据", "巷道绝对编码器数据"));
        baseDatas.add(new DWord("坡道绝对编码器数据", "坡道绝对编码器数据"));
        baseDatas.add(new DWord("校验位", "校验位"));
        baseDatas.add(new DWord("校验位", "校验位"));
        baseDatas.add(new DWord("校验位", "校验位"));
        baseDatas.add(new DWord("校验位", "校验位"));
        baseDatas.add(new DWord("校验位", "校验位"));
        baseDatas.add(new DWord("校验位", "校验位"));
    }

    /**
     * res参数获取
     */
    private void res() {
        baseDatas.add(new DWord("设备ID", "设置RES设备Id"));
        baseDatas.add(new DWord("服务器端口号", "res服务器端口号"));
        baseDatas.add(new DWord("校准方式", "设置RES校准方式"));
        baseDatas.add(new DWord("自动更新坐标", "自动更新坐标开关"));
        baseDatas.add(new DWord("是否打印", "设置RES是否打印"));
        baseDatas.add(new DWord("变速行驶开关", "设置RES变速行驶开关"));
        baseDatas.add(new DWord("小车类型", "小车类型选择"));
        baseDatas.add(new DWord("打印行驶心跳", "设置行驶心跳是否打印"));
        baseDatas.add(new DWord("打印油泵心跳", "设置油泵心跳是否打印"));
        baseDatas.add(new DWord("小车进行任务时的最大速度", "小车0x51指令下发的行驶速度"));
        baseDatas.add(new DWord("小车特殊位置的行驶速度", "小车在特殊位置行驶时的最大速度"));
        baseDatas.add(new DWord("报文版本", "报文版本"));
        baseDatas.add(new DWord("重发次数", "res往kcs发送报文重发次数"));
        baseDatas.add(new DWord("模拟器开关", "模拟器开关"));
        baseDatas.add(new DWord("底层串口类型", "底层串口类型"));
        baseDatas.add(new DWord("控制板类型", "控制板类型"));
        baseDatas.add(new DWord("地图申请空间X最大值", "地图申请空间X最大值"));
        baseDatas.add(new DWord("地图申请空间Y最大值", "地图申请空间Y最大值"));
        baseDatas.add(new DWord("地图申请空间Z最大值", "地图申请空间Z最大值"));
        baseDatas.add(new DWord("行驶指令使用接口0x51或者0x4f", "行驶指令使用接口0x51或者0x4f"));
        baseDatas.add(new DWord("提升机无八码止退功能开关", "提升机无八码止退功能开关"));
        baseDatas.add(new DWord("小车故障状态开关", "小车故障状态开关"));
        baseDatas.add(new DWord("小车低电量自动休眠开关", "小车低电量自动休眠开关"));
        baseDatas.add(new DWord("小车低电量自动休眠电量值", "小车低电量自动休眠电量值"));
        baseDatas.add(new DWord("Mac高段高", "设置RES-Mac高段"));
        baseDatas.add(new DWord("Mac高段低", "设置RES-Mac高段"));
        baseDatas.add(new DWord("Mac中段高", "设置RES-Mac中段"));
        baseDatas.add(new DWord("Mac中段低", "设置RES-Mac中段"));
        baseDatas.add(new DWord("Mac低段高", "设置RES-Mac低段"));
        baseDatas.add(new DWord("Mac低段低", "设置RES-Mac低段"));
        baseDatas.add(new DWord("Ip高段高", "设置RES-Ip高段"));
        baseDatas.add(new DWord("Ip高段低", "设置RES-Ip高段"));
        baseDatas.add(new DWord("Ip低段高", "设置RES-Ip低段"));
        baseDatas.add(new DWord("Ip低段低", "设置RES-Ip低段"));
        baseDatas.add(new DWord("网关高段高", "设置RES-网关高段"));
        baseDatas.add(new DWord("网关高段低", "设置RES-网关高段"));
        baseDatas.add(new DWord("网关低段高", "设置RES-网关低段"));
        baseDatas.add(new DWord("网关低段低", "设置RES-网关低段"));
        baseDatas.add(new DWord("子网掩码高段高", "设置RES-子网掩码高段"));
        baseDatas.add(new DWord("子网掩码高段低", "设置RES-子网掩码高段"));
        baseDatas.add(new DWord("子网掩码低段高", "设置RES-子网掩码低段"));
        baseDatas.add(new DWord("子网掩码低段低", "设置RES-子网掩码低段"));
    }

    private String getIp() {
        return getValue("Ip高段高").toString() + "." + getValue("Ip高段高").toString() + "."
                + getValue("Ip高段高").toString() + "." + getValue("Ip高段高").toString();
    }

    private Integer getXXX() {
        return getValue("Ip高段高").intValue() << 32 + getValue("Ip高段d").intValue();
    }

    /**
     * 行驶参数获取
     */
    private void recMoveParam() {
        baseDatas.add(new DWord("最大速度", "行驶速度"));
        baseDatas.add(new DWord("加速度", "行驶加速度"));
        baseDatas.add(new DWord("减速度", "行驶减速度"));
        baseDatas.add(new DWord("校准速度", "在校准的过程中的小车速度"));
        baseDatas.add(new DWord("校准超时时间", "校准过程中最大耗时时间"));
        baseDatas.add(new DWord("倍加福联系条码坡道K值", "倍加福联系条码坡道K值"));
        baseDatas.add(new DWord("倍加福联系条码巷道K值", "倍加福联系条码巷道K值"));
        baseDatas.add(new DWord("内部功能开关", "内部功能开关"));
        baseDatas.add(new DWord("根据换向次数重启功能", "换向次数达到后重启"));
        baseDatas.add(new DWord("车体类型", "对应小车版本"));
        baseDatas.add(new DWord("扫码器类型", "对应扫码器类型"));
        baseDatas.add(new DWord("激光雷达最小阈值判断", "激光雷达最短识别距离"));
        baseDatas.add(new DWord("激光雷达最大阈值判断", "激光雷达最长识别距离"));
        baseDatas.add(new DWord("关闭雷达剩余距离", "临时关闭雷达检测功能（在需要时）"));
        baseDatas.add(new DWord("雷达感应停止距离", "检测到障碍物时开始停止的距离"));
        baseDatas.add(new DWord("打开看门狗功能", "检测程序有无正常运行"));
        baseDatas.add(new DWord("心跳类型", "心跳类型res1.0or2.0"));
        baseDatas.add(new DWord("激光雷达个数", "实际小车雷达数"));
        baseDatas.add(new DWord("elmo驱动器通讯波特率", "elmo驱动器通讯波特率"));
        baseDatas.add(new DWord("控制板类型", "控制板类型"));
        baseDatas.add(new DWord("货位校准光电极性", "货位校准光电极性"));
        baseDatas.add(new DWord("巷道民德扫码校准正负偏差", "巷道民德扫码校准正负偏差"));
        baseDatas.add(new DWord("坡道民德扫码校准正负偏差", "坡道民德扫码校准正负偏差"));
        baseDatas.add(new DWord("巷道民德扫码校准目标像素", "巷道民德扫码校准目标像素"));
        baseDatas.add(new DWord("坡道民德扫码校准目标像素", "坡道民德扫码校准目标像素"));
        baseDatas.add(new DWord("巷道民德扫码减速像素", "巷道民德扫码减速像素"));
        baseDatas.add(new DWord("坡道民德扫码减速像素", "坡道民德扫码减速像素"));
        baseDatas.add(new DWord("托盘校准类型", "托盘校准类型"));
        baseDatas.add(new DWord("民德托盘一方向目标像素", "民德托盘一方向目标像素"));
        baseDatas.add(new DWord("民德托盘三方向目标像素", "民德托盘三方向目标像素"));
        baseDatas.add(new DWord("民德托盘左偏移像素", "民德托盘左偏移像素"));
        baseDatas.add(new DWord("民德托盘右偏移像素", "民德托盘右偏移像素"));
        baseDatas.add(new DWord("新大陆条码位数", "新大陆条码位数"));
        baseDatas.add(new DWord("民德扫码器的二次校准正负偏差", "民德扫码器的二次校准正负偏差"));
        baseDatas.add(new DWord("海康威视扫码器的校准正负偏差", "海康威视扫码器的校准正负偏差"));
        baseDatas.add(new DWord("倍加福扫码器的校准正负偏差", "倍加福扫码器的校准正负偏差"));
        baseDatas.add(new DWord("托盘扫码器的校准正负偏差", "托盘扫码器的校准正负偏差"));
        baseDatas.add(new DWord("第一次遇到障碍物停止的减速度", "第一次遇到障碍物停止的减速度"));
        baseDatas.add(new DWord("临时暂停时间", "临时暂停时间"));
        baseDatas.add(new DWord("蠕行阶段行驶速度", "蠕行阶段行驶速度"));
        baseDatas.add(new DWord("托盘的雷达的位移比例", "托盘的雷达的位移比例"));
        baseDatas.add(new DWord("第一次托盘感应停止距离", "第一次托盘感应停止距离"));
        baseDatas.add(new DWord("托盘最终停止的距离，上报暂停", "托盘最终停止的距离，上报暂停"));
        baseDatas.add(new DWord("停下后托盘激光雷达的波动范围", "停下后托盘激光雷达的波动范围"));
        baseDatas.add(new DWord("蠕行阶段行驶时托盘激光雷达的波动范围", "蠕行阶段行驶时托盘激光雷达的波动范围"));
        baseDatas.add(new DWord("托盘激光连续N次的触发", "托盘激光连续N次的触发"));
        baseDatas.add(new DWord("四周障碍物位移和速度比例", "四周障碍物位移和速度比例"));
        baseDatas.add(new DWord("四周障碍物感应的最远距离", "四周障碍物感应的最远距离"));
        baseDatas.add(new DWord("四周障碍物感应操作的最近距离", "四周障碍物感应操作的最近距离"));
        baseDatas.add(new DWord("停下后四周障碍物激光雷达的波动范围", "停下后四周障碍物激光雷达的波动范围"));
        baseDatas.add(new DWord("蠕行阶段行驶时四周障碍物激光雷达的波动范围", "蠕行阶段行驶时四周障碍物激光雷达的波动范围"));
        baseDatas.add(new DWord("四周障碍物激光连续N次的触发", "四周障碍物激光连续N次的触发"));
        baseDatas.add(new DWord("新益昌版本的默认加速度的加速度", "新益昌版本的默认加速度的加速度"));
        baseDatas.add(new DWord("新益昌驱动器重启时间", "新益昌驱动器重启时间"));
        baseDatas.add(new DWord("托盘校准速度", "托盘校准速度"));
        baseDatas.add(new DWord("一次托盘校准时间", "一次托盘校准时间"));
        baseDatas.add(new DWord("托盘倾斜判断激光", "托盘倾斜判断激光"));
        baseDatas.add(new DWord("一次性校准速度切入限制校准速度的倍数", "一次性校准速度切入限制校准速度的倍数(xyc)"));
        baseDatas.add(new DWord("一次性校准减少的偏移量mm", "一次性校准减少的偏移量mm(xyc)"));
        baseDatas.add(new DWord("速度模式加减速度（仅限于埃斯顿驱动器）", "aisidun(非sva模式):速度行驶的加速时间，表示多少ms到达目标速度 aisidun(sva模式)：速度/加速度=从0加到速度需要的时间（s）"));
        baseDatas.add(new DWord("行驶切换校准时的减速度（仅限于埃斯顿驱动器）", "aisidun(非sva模式):速度行驶的加速时间，表示多少ms从目标速度到达0 aisidun(sva模式)：速度/减速度=从速度减到0需要的时间（s）"));
        baseDatas.add(new DWord("新益昌失速时间判断 ( ms)", "新益昌失速时间判断 ( ms)"));
        baseDatas.add(new DWord("海康威视版本选择", "为了适配海康威视扫码器的版本"));
        baseDatas.add(new DWord("提升机判断无八码距离", "提升机判断无八码距离"));
        baseDatas.add(new DWord("resistanceRelayDelayTime", "电阻继电器延时时间"));
    }

    /**
     *  设置单个参数
     */
    private void setOneParam() {
        baseDatas.add(new DWord("resultParam","执行结果参数"));
    }

    public Integer getResult() {
        return getValue("执行结果");
    }

    @Override
    public boolean checkMessage(byte[] recData, RgvMessageType rgvMessageType, Integer sendLife) throws IOException {
        switch (messageType) {
            case READ_RES_VERSION:
            case READ_LIFT_VERSION:
            case READ_DRIVER_VERSION:
                int paramNum = recData[10];
                readVersion(paramNum);
                break;
            default:
                break;
        }

        checkMessageComplete(recData, this.getMessageSize());

        if (WcsFuncUtil.combineToWord(recData[recData.length - 3], recData[recData.length - 4]) != calcCrc(recData, recData.length - 4)) {
            LoggerUtil.warn("crc校验错误：" + Arrays.toString(recData), this.getClass());
            throw new IOException("crc校验错误");
        }

        readMessage(recData);

        int messageLength = getMessageLength();
        if (recData.length != messageLength) {
            throw new RuntimeException("解析的报文长度与接收的实际长度不一致:" + Arrays.toString(recData));
        }

        try {
            if (sendLife != null && getMessageLife().intValue() != sendLife) {
                LoggerUtil.warn("收发生命不一致-->发送：" + sendLife + ", 接收:" + getMessageLife(), this.getClass());
                throw new FrameLocationException("收发生命不一致-->发送：" + sendLife + ", 接收:" + getMessageLife());
            }
        } catch (NullPointerException e) {
            WcsUtil.exceptionLog(e, this.getClass());
        }

        if (getMessageType().intValue() != rgvMessageType.getValue()) {
            LoggerUtil.warn("报文类型错误：" + Arrays.toString(recData), this.getClass());
            throw new FrameLocationException("报文类型错误");
        }

        analyzeMessage();

        return true;
    }

    private void analyzeMessage() {
        // 1. 接受成功 2. 接受重复
        if (getResult() != 1 && getResult() != 2) {
            throw new OrderExecuteException(getRgv().getRgvDB().getRgvNo(), getResult(),
                    codedbService.getCodeDescByFault(getResult(), CodeType.RES_ERROR_CODE));
        }
    }

    public Integer getResultParam(DebugCommType type) {
        if (type == DebugCommType.SET_ONE_PARAM) {
            return getValue("resultParam");
        } else if(type == DebugCommType.RES_PARAM) {
            setResParam();
        } else if (type == DebugCommType.DRIVING_PARAM) {
            setDrivingParam();
        } else if (type == DebugCommType.LIFT_PARAM) {
            setLiftParam();
        } else if (type == DebugCommType.GET_RES_VERSION) {
            setResVersion();
        } else {
            throw new RuntimeException("不支持的调试指令类型:" + type);
        }

        return getValue("设备ID");
    }

    public int getParamNum() {
        return getValue("参数个数");
    }

    private String analyzeVersion(int length) {
        length *= 4;
        char[] versionArray = new char[length];
        for (int i = 0; i < length; i++) {
            versionArray[i] = (char) getValue("v" + i).byteValue();
        }

        return String.valueOf(versionArray);
    }

    private void setResVersion() {
        //RES+3.1_v0.0.54.a2xj.bin
        ResParam resParam = getRgv().getResParam();
        String version = analyzeVersion(getParamNum());
        LoggerUtil.info(this.getRgv().getRgvName() + " 当前res版本:" + version, this.getClass());
        resParam.setResVersion(version);
    }

    private void setLiftVersion() {
        ResParam resParam = getRgv().getResParam();
        String version = analyzeVersion(getParamNum());
        resParam.setLiftVersion(version);
    }

    private void setDriveVesion() {
        //X34C.0809P12_v11.0.2.48_t5(1).bin
        ResParam resParam = getRgv().getResParam();
        String version = analyzeVersion(getParamNum());
        resParam.setDriverVersion(version);
    }

    private Integer getMessageLength() {
        return getValue("报文长度");
    }

    private Integer getFirmwareVersion() {
        return getValue("固件版本");
    }

    private Integer getRoadwaySensorOne() {
        return getValue("巷道传感器1数据");
    }

    private Integer getRoadwaySensorTwo() {
        return getValue("巷道传感器2数据");
    }

    private Integer getRampSensorOne() {
        return getValue("坡道传感器1数据");
    }

    private Integer getRampSensorTwo() {
        return getValue("坡道传感器2数据");
    }

    private Integer getPalletDownSensorOne() {
        return getValue("托盘降传感器1数据");
    }

    private Integer getPalletDownSensorTwo() {
        return getValue("托盘降传感器2数据");
    }

    private Integer getPalletUpSensorOne() {
        return getValue("托盘升传感器1数据");
    }

    private Integer getPalletUpSensorTwo() {
        return getValue("托盘升传感器2数据");
    }

    private Integer getSensorError() {
        return getValue("传感器误差值");
    }

    private Integer getHeightDiff() {
        return getValue("液压动作高度差");
    }

    private Integer getDelayTime() {
        return getValue("液压到位后延迟时间");
    }

    private Integer getDriveMaxSpeed(){
        return getValue("驱动默认最大速度");
    }

    private Integer getDriveAcc() {
        return getValue("驱动默认加速度");
    }

    private Integer getDrivDec() {
        return getValue("驱动默认减速度");
    }

    private Integer getFlatDelay() {
        return getValue("溢流调平延迟时间");
    }

    private Integer getContactOpenTime() {
        return getValue("串联打开时间");
    }

    private Integer getParallelOpenTime() {
        return getValue("并联打开时间");
    }

    private Integer getPalletUp() {
        return getValue("托盘升绝对编码器数据");
    }

    private Integer getPalletDown() {
        return getValue("托盘降绝对编码器数据");
    }

    private Integer getRoadwayValue() {
        return getValue("巷道绝对编码器数据");
    }

    private Integer getRampValue() {
        return getValue("巷道绝对编码器数据");
    }

    private void setLiftParam() {
        LiftParam liftParam = getRgv().getLiftParam();
        liftParam.setRgvNo(getRgv().getRgvDB().getRgvNo());
        liftParam.setFirmwareVersion(getFirmwareVersion());
        liftParam.setRoadwaySensorOne(getRoadwaySensorOne());
        liftParam.setRoadwaySensorTwo(getRoadwaySensorTwo());
        liftParam.setRampSensorOne(getRampSensorOne());
        liftParam.setRampSensorTwo(getRampSensorTwo());
        liftParam.setPalletDownSensorOne(getPalletDownSensorOne());
        liftParam.setPalletDownSensorTwo(getPalletDownSensorTwo());
        liftParam.setPalletUpSensorOne(getPalletUpSensorOne());
        liftParam.setPalletUpSensorTwo(getPalletUpSensorTwo());
        liftParam.setSensorError(getSensorError());
        liftParam.setHeightDiff(getHeightDiff());
        liftParam.setDelayTime(getDelayTime());
        liftParam.setDriveMaxSpeed(getDriveMaxSpeed());
        liftParam.setDriveAcc(getDriveAcc());
        liftParam.setDrivDec(getDrivDec());
        liftParam.setFlatDelay(getFlatDelay());
        liftParam.setContactOpenTime(getContactOpenTime());
        liftParam.setParallelOpenTime(getParallelOpenTime());
        liftParam.setPalletUp(getPalletUp());
        liftParam.setPalletDown(getPalletDown());
        liftParam.setRoadwayValue(getRoadwayValue());
        liftParam.setRampValue(getRampValue());
    }


    private Integer getDeviceNo() {
        return getValue("设备ID");
    }

    private Integer getDrivingSpeed() {
        return getValue("小车进行任务时的最大速度");
    }

    private Integer getMaxSpeed() {
        return getValue("最大速度");
    }

    private Integer getAcceleration() {
        return getValue("加速度");
    }

    private Integer getDeceleration() {
        return getValue("减速度");
    }

    private Integer getCorrSpeed() {
        return getValue("校准速度");
    }

    private Integer getCorrOvertime() {
        return getValue("校准超时时间");
    }

    private Integer getVehicleType() {
        return getValue("车体类型");
    }

    private Integer getScanType() {
        return getValue("扫码器类型");
    }

    private Integer getMinRadar() {
        return getValue("激光雷达最小阈值判断");
    }

    private Integer getMaxRadar() {
        return getValue("激光雷达最大阈值判断");
    }

    private Integer getCloseResidualRange() {
        return getValue("关闭雷达剩余距离");
    }

    private Integer getRadarStopDistance() {
        return getValue("雷达感应停止距离");
    }

    private Integer getPalletCalibrationSpeed() {
        return getValue("托盘校准速度");
    }

    private Integer getOnetimePalCaliTime() {
        return getValue("一次托盘校准时间");
    }

    private Integer getPalletJudgLaser() {
        return getValue("托盘倾斜判断激光");
    }

    private Integer getHeartType() {
        return getValue("心跳类型");
    }

    private Integer getBeijiaBarRamp() {
        return getValue("倍加福联系条码坡道K值");
    }

    private Integer getBeijiaBarRoadway() {
        return getValue("倍加福联系条码巷道K值");
    }


    private Integer getInternalFunction(){
        return getValue("内部功能开关");
    }
    /*private ArrayList<Integer> getInternalFunction() {
        ArrayList<Integer> internalFunction = new ArrayList<>();
        String binary = Integer.toBinaryString(getValue("内部功能开关"));
        int power = 0;
        for (int i = binary.length(); i > 0; i--) {
            char a = binary.charAt(i - 1);
            if ( a == '1') {
                internalFunction.add((int)Math.pow(2, power));
                power++;
            }else if (a == '0') {
                power++;
            }
        }
        return internalFunction;
    }*/

    private Integer getCommutationRestart() {
        return getValue("根据换向次数重启功能");
    }

    private Integer getOpenWatchdog() {
        return getValue("打开看门狗功能");
    }

    private Integer getRadarNum() {
        return getValue("激光雷达个数");
    }

    private Integer getElmoBaudRate() {
        return getValue("elmo驱动器通讯波特率");
    }

    private Integer getControlBoardType() {
        return getValue("控制板类型");
    }

    private Integer getLocationCalibration() {
        return getValue("货位校准光电极性");
    }

    private Integer getMindeRoadwayDiff() {
        return getValue("巷道民德扫码校准正负偏差");
    }

    private Integer getMindeRampDiff() {
        return getValue("坡道民德扫码校准正负偏差");
    }

    private Integer getMindeRoadwayTargetPx() {
        return getValue("巷道民德扫码校准目标像素");
    }

    private Integer getMindeRampTargetPx() {
        return getValue("坡道民德扫码校准目标像素");
    }

    private Integer getMindeRoadwayDecePx() {
        return getValue("巷道民德扫码减速像素");
    }

    private Integer getMindeRampDecePx() {
        return getValue("坡道民德扫码减速像素");
    }

    private Integer getPalletCalibrationType() {
        return getValue("托盘校准类型");
    }

    private Integer getMindePalletOneDir() {
        return getValue("民德托盘一方向目标像素");
    }

    private Integer getMindePalletThreeDir() {
        return getValue("民德托盘三方向目标像素");
    }

    private Integer getMindePalletLeft() {
        return getValue("民德托盘左偏移像素");
    }

    private Integer getMindePalletRight() {
        return getValue("民德托盘右偏移像素");
    }

    private Integer getXindaBar() {
        return getValue("新大陆条码位数");
    }

    private Integer getMindeTwotime() {
        return getValue("民德扫码器的二次校准正负偏差");
    }

    private Integer getHkDiff() {
        return getValue("海康威视扫码器的校准正负偏差");
    }

    private Integer getBeijiaDiff() {
        return getValue("倍加福扫码器的校准正负偏差");
    }

    private Integer getPalletDiff() {
        return getValue("托盘扫码器的校准正负偏差");
    }

    private Integer getOnetimeDece() {
        return getValue("第一次遇到障碍物停止的减速度");
    }

    private Integer getTemporaryPauseTime() {
        return getValue("临时暂停时间");
    }

    private Integer getSlowSpeed() {
        return getValue("蠕行阶段行驶速度");
    }

    private Integer getRadarDisplace() {
        return getValue("托盘的雷达的位移比例");
    }

    private Integer getFirstStop() {
        return getValue("第一次托盘感应停止距离");
    }

    private Integer getLastStop() {
        return getValue("托盘最终停止的距离，上报暂停");
    }

    private Integer getStopRadar() {
        return getValue("停下后托盘激光雷达的波动范围");
    }

    private Integer getSlowMoveRadar() {
        return getValue("蠕行阶段行驶时托盘激光雷达的波动范围");
    }

    private Integer getPalletTrigger() {
        return getValue("托盘激光连续N次的触发");
    }

    private Integer getDisplacementVelocityRatio() {
        return getValue("四周障碍物位移和速度比例");
    }

    private Integer getLongestDistance() {
        return getValue("四周障碍物感应的最远距离");
    }

    private Integer getNearesDistance() {
        return getValue("四周障碍物感应操作的最近距离");
    }

    private Integer getStopAroundRadar() {
        return getValue("停下后四周障碍物激光雷达的波动范围");
    }

    private Integer getSlowAroundRadar() {
        return getValue("蠕行阶段行驶时四周障碍物激光雷达的波动范围");
    }

    private Integer getAroundRadarTrigger() {
        return getValue("四周障碍物激光连续N次的触发");
    }

    private Integer getXinyiAcc() {
        return getValue("新益昌版本的默认加速度的加速度");
    }

    private Integer getXinyiRestartTime() {
        return getValue("新益昌驱动器重启时间");
    }

    private void setDrivingParam() {
        DrivingParam drivingParam = getRgv().getDrivingParam();
        drivingParam.setRgvNo(getRgv().getRgvDB().getRgvNo());
        drivingParam.setMaxSpeed(getMaxSpeed());
        drivingParam.setAcceleration(getAcceleration());
        drivingParam.setDeceleration(getDeceleration());
        drivingParam.setCorrSpeed(getCorrSpeed());
        drivingParam.setCorrOvertime(getCorrOvertime());
        drivingParam.setBeijiaBarRamp(getBeijiaBarRamp());
        drivingParam.setBeijiaBarRoadway(getBeijiaBarRoadway());
        drivingParam.setInternalFunction(getInternalFunction());
        drivingParam.setCommutationRestart(getCommutationRestart());
        drivingParam.setVehicleType(getVehicleType());
        drivingParam.setScanType(getScanType());
        drivingParam.setMinRadar(getMinRadar());
        drivingParam.setMaxRadar(getMaxRadar());
        drivingParam.setCloseResidualRange(getCloseResidualRange());
        drivingParam.setRadarStopDistance(getRadarStopDistance());
        drivingParam.setOpenWatchdog(getOpenWatchdog());
        drivingParam.setHeartType(getHeartType());
        drivingParam.setRadarNum(getRadarNum());
        drivingParam.setElmoBaudRate(getElmoBaudRate());
        drivingParam.setControlBoardType(getControlBoardType());
        drivingParam.setLocationCalibration(getLocationCalibration());
        drivingParam.setMindeRoadwayDiff(getMindeRoadwayDiff());
        drivingParam.setMindeRampDiff(getMindeRampDiff());
        drivingParam.setMindeRoadwayTargetPx(getMindeRoadwayTargetPx());
        drivingParam.setMindeRampTargetPx(getMindeRampTargetPx());
        drivingParam.setMindeRoadwayDecePx(getMindeRoadwayDecePx());
        drivingParam.setMindeRampDecePx(getMindeRampDecePx());
        drivingParam.setPalletCalibrationType(getPalletCalibrationType());
        drivingParam.setMindePalletOneDir(getMindePalletOneDir());
        drivingParam.setMindePalletThreeDir(getMindePalletThreeDir());
        drivingParam.setMindePalletLeft(getMindePalletLeft());
        drivingParam.setMindePalletRight(getMindePalletRight());
        drivingParam.setXindaBar(getXindaBar());
        drivingParam.setMindeTwotime(getMindeTwotime());
        drivingParam.setHkDiff(getHkDiff());
        drivingParam.setBeijiaDiff(getBeijiaDiff());
        drivingParam.setPalletDiff(getPalletDiff());
        drivingParam.setOnetimeDece(getOnetimeDece());
        drivingParam.setTemporaryPauseTime(getTemporaryPauseTime());
        drivingParam.setSlowSpeed(getSlowSpeed());
        drivingParam.setRadarDisplace(getRadarDisplace());
        drivingParam.setFirstStop(getFirstStop());
        drivingParam.setLastStop(getLastStop());
        drivingParam.setStopRadar(getStopRadar());
        drivingParam.setSlowMoveRadar(getSlowMoveRadar());
        drivingParam.setPalletTrigger(getPalletTrigger());
        drivingParam.setDisplacementVelocityRatio(getDisplacementVelocityRatio());
        drivingParam.setLongestDistance(getLongestDistance());
        drivingParam.setNearesDistance(getNearesDistance());
        drivingParam.setStopAroundRadar(getStopAroundRadar());
        drivingParam.setSlowAroundRadar(getSlowAroundRadar());
        drivingParam.setAroundRadarTrigger(getAroundRadarTrigger());
        drivingParam.setXinyiAcc(getXinyiAcc());
        drivingParam.setXinyiRestartTime(getXinyiRestartTime());
        drivingParam.setPalletCalibrationSpeed(getPalletCalibrationSpeed());
        drivingParam.setOnetimePalCaliTime(getOnetimePalCaliTime());
        drivingParam.setPalletJudgLaser(getPalletJudgLaser());

    }

    private Integer getPort()  {
        return getValue("服务器端口号");
    }

    private Integer getLocation() {
        int location = getValue("校准方式") / 100000 % 10 * 100000;
        return location;
    }

    private Integer getPassWay() {
        int passway = getValue("校准方式") / 10000 % 10 * 10000;
        return passway;
    }

    private Integer getHoist() {
        int hoist = getValue("校准方式") / 1000 % 10 * 1000;
        return hoist;
    }

    private Integer getChargPoint() {
        int chargPoint = getValue("校准方式") / 100 % 10 * 100;
        return chargPoint;
    }

    private Integer getInPort() {
        int inPort = getValue("校准方式") / 10 % 10 * 10;
        return inPort;
    }

    private Integer getOutPort() {
        int outPort = getValue("校准方式") % 10;
        return outPort;
    }

    private Integer getAutoUpdae() {
        return getValue("自动更新坐标");
    }

    private Integer getResPrint() {
        return getValue("是否打印");
    }

    private Integer getResDrivingSwitch() {
        return getValue("变速行驶开关");
    }

    private Integer getTrolleyType() {
        return getValue("小车类型");
    }

    private Integer getHeartPrint() {
        return getValue("打印行驶心跳");
    }

    private Integer getPumpHeartPrint() {
        return getValue("打印油泵心跳");
    }

    private Integer getSpeciDriSpeed() {
        return getValue("小车特殊位置的行驶速度");
    }

    private Integer getMessageVersion() {
        return getValue("报文版本");
    }

    private Integer getRepeatTime() {
        return getValue("重发次数");
    }

    private Integer getSerialPortType() {
        return getValue("底层串口类型");
    }

    private Integer getContrBoardType() {
        return getValue("控制板类型");
    }

    private Integer getMapX() {
        return getValue("地图申请空间X最大值");
    }

    private Integer getMapY() {
        return getValue("地图申请空间Y最大值");
    }

    private Integer getMapZ() {
        return getValue("地图申请空间Z最大值");
    }

    private Integer getDrivingCmd() {
        return getValue("行驶指令使用接口0x51或者0x4f");
    }

    private Integer getLiftSwitch() {
        return getValue("提升机无八码止退功能开关");
    }

    private Integer getFaultSwitch() {
        return getValue("小车故障状态开关");
    }

    private Integer getLowBatterySwitch() {
        return getValue("小车低电量自动休眠开关");
    }

    private Integer getLowBatteryValue() {
        return getValue("小车低电量自动休眠开关");
    }

    private void setResParam() {
        ResParam resParam = getRgv().getResParam();
        resParam.setRgvNo(getRgv().getRgvDB().getRgvNo());
        resParam.setDeviceNo(getDeviceNo());
        resParam.setPort(getPort());
        resParam.setLocation(getLocation());
        resParam.setPassWay(getPassWay());
        resParam.setHoist(getHoist());
        resParam.setChargPoint(getChargPoint());
        resParam.setInPort(getInPort());
        resParam.setOutPort(getOutPort());
        resParam.setAutoUpdae(getAutoUpdae());
        resParam.setResPrint(getResPrint());
        resParam.setResDrivingSwitch(getResDrivingSwitch());
        resParam.setTrolleyType(getTrolleyType());
        resParam.setHeartPrint(getHeartPrint());
        resParam.setPumpHeartPrint(getPumpHeartPrint());
        resParam.setDrivingSpeed(getDrivingSpeed());
        resParam.setSpeciDriSpeed(getSpeciDriSpeed());
        resParam.setMessageVersion(getMessageVersion());
        resParam.setRepeatTime(getRepeatTime());
        resParam.setSerialPortType(getSerialPortType());
        resParam.setContrBoardType(getContrBoardType());
        resParam.setMapX(getMapX());
        resParam.setMapY(getMapY());
        resParam.setMapZ(getMapZ());
        resParam.setDrivingCmd(getDrivingCmd());
        resParam.setLiftSwitch(getLiftSwitch());
        resParam.setFaultSwitch(getFaultSwitch());
        resParam.setLowBatterySwitch(getLowBatterySwitch());
        resParam.setLowBatteryValue(getLowBatteryValue());
    }

    @Override
    public Integer getMessageLife() {
        return getValue("生命");
    }

    @Override
    public Integer getMessageType() {
        return getValue("报文类型");
    }

    private void checkMessageComplete(byte[] recData, int messageSize) {
        if (recData.length < messageSize) {
            int dataNum = messageSize - recData.length;

            if ((dataNum % 4) == 0) {
                removeParamNotInProtocol(dataNum / 4);
                return;
            }

            throw new MessageCompleteException("接收数据长度：" + recData.length + "，小于报文理论长度：" + messageSize);
        } else if (recData.length > messageSize) {
            int dataNum = recData.length - messageSize;

            if ((dataNum % 4) == 0) {
                addParamNotInProtocol(dataNum / 4);
                return;
            }
            throw new MessageErrorException("接收数据长度：" + recData.length + "，大于报文理论长度：" + messageSize);
        }
    }

    /**
     * 如果res版本过低，数据可能会比现在的协议内容少，删除少的部分后进行解析
     * @param num
     */
    private void removeParamNotInProtocol(int num) {
        for (int i = 0; i < num; i++) {
            baseDatas.remove(baseDatas.size() - 1 - END_FRAME_LENGTH);
        }
    }

    /**
     * 如果res版本升级，数据可能会比现在的协议内容多，不够的部分用预留填充后进行解析
     * @param num
     */
    private void addParamNotInProtocol(int num) {
        for (int i = 0; i < num; i++) {
            baseDatas.add(baseDatas.size() - END_FRAME_LENGTH, new DWord("res" + i, "协议没有"));
        }
    }
}
